package com.huanke.iot.manage.service.device.operate;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.huanke.iot.base.api.ApiResponse;
import com.huanke.iot.base.constant.RetCode;
import com.huanke.iot.base.dao.customer.CustomerUserMapper;
import com.huanke.iot.base.dao.device.DeviceDataHistoryMapper;
import com.huanke.iot.base.dao.device.DeviceMapper;
import com.huanke.iot.base.dao.device.ability.DeviceAbilityMapper;
import com.huanke.iot.base.dao.device.ability.DeviceAbilityOptionMapper;
import com.huanke.iot.base.dao.device.alarm.DeviceAlarmDataMapper;
import com.huanke.iot.base.dao.device.data.DeviceOperLogMapper;
import com.huanke.iot.base.dao.device.stat.DeviceSensorStatMapper;
import com.huanke.iot.base.dao.device.typeModel.DeviceModelAbilityMapper;
import com.huanke.iot.base.dao.device.typeModel.DeviceModelMapper;
import com.huanke.iot.base.dao.user.UserManagerMapper;
import com.huanke.iot.base.enums.SensorTypeEnums;
import com.huanke.iot.base.po.customer.CustomerUserPo;
import com.huanke.iot.base.po.device.DeviceDataHistoryPo;
import com.huanke.iot.base.po.device.DevicePo;
import com.huanke.iot.base.po.device.ability.DeviceAbilityOptionPo;
import com.huanke.iot.base.po.device.ability.DeviceAbilityPo;
import com.huanke.iot.base.po.device.alarm.DeviceAlarmDataPo;
import com.huanke.iot.base.po.device.data.DeviceOperLogPo;
import com.huanke.iot.base.po.device.stat.DeviceSensorStatPo;
import com.huanke.iot.base.po.device.typeModel.DeviceModelAbilityPo;
import com.huanke.iot.base.po.device.typeModel.DeviceModelPo;
import com.huanke.iot.base.po.user.User;
import com.huanke.iot.manage.service.device.typeModel.DeviceModelService;
import com.huanke.iot.manage.vo.request.device.operate.DeviceDataQueryRequest;
import com.huanke.iot.manage.vo.response.device.BaseListVo;
import com.huanke.iot.manage.vo.response.device.data.*;
import com.huanke.iot.manage.vo.response.format.ModelFormatVo;
import lombok.extern.slf4j.Slf4j;
import org.assertj.core.util.Lists;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author haoshijing
 * @version 2018年05月30日 13:25
 **/
@Service
@Slf4j
public class DeviceDataService {

    @Autowired
    private DeviceModelService deviceModelService;

    @Autowired
    private DeviceOperLogMapper deviceOperLogMapper;

    @Autowired
    private DeviceSensorStatMapper deviceSensorStatMapper;

    @Autowired
    private CustomerUserMapper customerUserMapper;

    @Autowired
    private UserManagerMapper userMapper;

    @Autowired
    private DeviceMapper deviceMapper;

    @Autowired
    private DeviceAbilityMapper deviceAbilityMapper;


    @Autowired
    private DeviceAbilityOptionMapper deviceAbilityOptionMapper;

    @Autowired
    private DeviceModelMapper deviceModelMapper;

    @Autowired
    private DeviceAlarmDataMapper deviceAlarmMapper;

    @Autowired
    private DeviceModelAbilityMapper deviceModelAbilityMapper;

    @Autowired
    private DeviceDataHistoryMapper deviceDataHistoryMapper;


    public ApiResponse<List<DeviceOperLogVo>> queryOperLog(DeviceDataQueryRequest request) throws Exception {
        DeviceOperLogPo queryPo = new DeviceOperLogPo();
        queryPo.setDeviceId(request.getDeviceId());
        Integer offset = (request.getPage() - 1) * request.getLimit();
        Integer limit = request.getLimit();
        List<DeviceOperLogPo> deviceOperLogPoList = deviceOperLogMapper.selectList(queryPo, limit, offset);
        List<DeviceAbilityPo> deviceAbilityPos = deviceAbilityMapper.queryAll();
        if (null == deviceOperLogPoList || 0 == deviceOperLogPoList.size()) {
            return new ApiResponse<>(RetCode.OK, "暂无数据");
        }
        List<DeviceOperLogVo> deviceOperLogVoList = deviceOperLogPoList.stream().filter(temp -> {
            return deviceAbilityPos.stream().anyMatch(deviceAbilityPo -> deviceAbilityPo.getDirValue().equals(temp.getFuncId()));
        }).map(deviceOperLogPo -> {
            DeviceOperLogVo deviceOperLogVo = new DeviceOperLogVo();
            BeanUtils.copyProperties(deviceOperLogPo, deviceOperLogVo);
            deviceOperLogVo.setOperateTime(deviceOperLogPo.getCreateTime());
            //获取操作人名字
            if (null != deviceOperLogPo.getOperUserId()) {
                //根据操作来源读取不同的客户名称，1-1-h5,2-安卓,3-管理端，1、2读取用户表，3读取客户表
                if (1 == deviceOperLogPo.getOperType() || 2 == deviceOperLogPo.getOperType()) {
                    CustomerUserPo customerUserPo = this.customerUserMapper.selectByUserId(deviceOperLogPo.getOperUserId());
                    if (null != customerUserPo) {
                        deviceOperLogVo.setOperName(customerUserPo.getNickname());
                    } else {
                        deviceOperLogVo.setOperName("未知用户");
                    }
                } else {
                    User userPo = this.userMapper.selectById(deviceOperLogPo.getOperUserId());
                    if (null != userPo) {
                        deviceOperLogVo.setOperName(userPo.getNickName());
                    } else {
                        deviceOperLogVo.setOperName("未知用户");
                    }
                }
            }

            Optional<DeviceAbilityPo> optional = deviceAbilityPos.stream().filter(deviceAbilityPo -> deviceAbilityPo.getDirValue().equals(deviceOperLogPo.getFuncId())).findFirst();
            Integer ablityId = optional.get().getId();

            List<DeviceAbilityOptionPo> deviceAbilityOptionPos = deviceAbilityOptionMapper.selectOptionsByAbilityId(ablityId);
            //设置操作名称名称
            deviceOperLogVo.setFuncName(optional.get().getAbilityName());

            Optional<DeviceAbilityOptionPo> deviceAbilityOptionPo = deviceAbilityOptionPos.stream().filter(optionPo -> {
                return optionPo.getOptionValue().equals(deviceOperLogPo.getFuncValue());
            }).findFirst();
            if (deviceAbilityOptionPo.isPresent()) {
                deviceOperLogVo.setFuncValue(deviceAbilityOptionPo.get().getOptionName());
            }
            return deviceOperLogVo;
        }).collect(Collectors.toList());
        return new ApiResponse<>(RetCode.OK, "设备日志查询成功", deviceOperLogVoList);
    }

    public ApiResponse<BaseListVo> queryOperLogList(DeviceDataQueryRequest request) throws Exception {
        BaseListVo baseListVo = new BaseListVo();
        DeviceOperLogPo queryPo = new DeviceOperLogPo();
        queryPo.setDeviceId(request.getDeviceId());
        ApiResponse<List<DeviceOperLogVo>> operLogRtn = queryOperLog(request);
        if (operLogRtn != null && operLogRtn.getCode() != RetCode.OK) {
            return new ApiResponse<>(RetCode.ERROR, operLogRtn.getMsg());
        }
        Integer totalCount = this.deviceOperLogMapper.selectOperCount(queryPo);
        baseListVo.setDataList(operLogRtn.getData());
        baseListVo.setTotalCount(totalCount);
        return new ApiResponse<>(RetCode.OK, "查询设备操作日志与总数成功", baseListVo);
    }

    //按页和开始结束时间查询设备数据
    public ApiResponse<List<JSONObject>> queryDeivceSensorData(DeviceDataQueryRequest deviceDataQueryRequest) throws Exception {
        Integer deviceId = deviceDataQueryRequest.getDeviceId();
        DevicePo devicePo = deviceMapper.selectById(deviceId);
        Integer modelId = devicePo.getModelId();
        DeviceSensorStatPo deviceSensorStatPo = new DeviceSensorStatPo();
        deviceSensorStatPo.setDeviceId(deviceId);
        Integer offset = (deviceDataQueryRequest.getPage() - 1) * deviceDataQueryRequest.getLimit();
        Integer limit = deviceDataQueryRequest.getLimit();

        List<DeviceDataHistoryPo> deviceDataHistoryPoList = this.deviceDataHistoryMapper.selectByDeviceId(deviceId, limit, offset);
        if (null == deviceDataHistoryPoList || 0 == deviceDataHistoryPoList.size()) {
            return new ApiResponse<>(RetCode.OK, "暂无数据");
        }
        List<JSONObject> deviceSensorStatVoList = deviceDataHistoryPoList.stream().map(eachPo -> {
            DeviceSensorStatVo deviceSensorStatVo = new DeviceSensorStatVo();
            JSONObject resultObject = new JSONObject();
            resultObject.put("deviceId", eachPo.getDeviceId());
            resultObject.put("startTime", eachPo.getDataTime().getTime());
            //查询该设备 型号 都有哪些功能项目是isCheck
            List<DeviceModelAbilityPo> deviceModelAbilityPos = deviceModelAbilityMapper.selectByIsCheck(modelId);
            List<String> dirList = deviceModelAbilityPos.stream().map(deviceModelAbilityPo -> deviceModelAbilityPo.getDirValue()).collect(Collectors.toList());
            //遍历历史数据项目，还原json
            String hisDir = eachPo.getHisDir();
            JSONArray jsonArray = JSONArray.parseArray(hisDir);
            for (Iterator iterator = jsonArray.iterator(); iterator.hasNext();) {
                JSONObject jb = (JSONObject) iterator.next();
                String dir = (String) jb.get("dir");
                String dirValue = jb.get("dirValue").toString();

                Double multiple = deviceModelAbilityMapper.selectMultipleByModelIdAndDirValue1(modelId, dir);
                String replace = String.format("%.2f", (Double.valueOf(dirValue) * (multiple == null ? 1 : multiple))).replace(".00", "");
                if(replace.contains(".") && replace.endsWith("0")){
                    replace = replace.substring(0, replace.length()-1);
                }
                resultObject.put(deviceAbilityMapper.selectAbilityCodeByDirValue(dir), replace);
            }
            return resultObject;
        }).collect(Collectors.toList());
        return new ApiResponse<>(RetCode.OK, "查询成功", deviceSensorStatVoList);
    }

    public ApiResponse<BaseListVo> queryDeivceSensorDataList(DeviceDataQueryRequest request) throws Exception {
        BaseListVo baseListVo = new BaseListVo();
        DeviceDataHistoryPo queryPo = new DeviceDataHistoryPo();
        queryPo.setDeviceId(request.getDeviceId());
        ApiResponse<List<JSONObject>> sensorDataRtn = queryDeivceSensorData(request);
        if (sensorDataRtn != null && sensorDataRtn.getCode() != RetCode.OK) {
            return new ApiResponse<>(RetCode.ERROR, sensorDataRtn.getMsg());
        }
        Integer totalCount = this.deviceDataHistoryMapper.selectCount(queryPo);
        baseListVo.setDataList(sensorDataRtn.getData());
        baseListVo.setTotalCount(totalCount);
        return new ApiResponse<>(RetCode.OK, "查询设备操作日志与总数成功", baseListVo);
    }

    //按页查询设备工作日志（开关机时间、上离线时间）
    public ApiResponse<List<DeviceWorkLogVo>> queryDeviceWorkData(DeviceDataQueryRequest request) {
        return queryDeviceWorkData(request, false);
    }

    public ApiResponse<List<DeviceWorkLogVo>> queryDeviceWorkData(DeviceDataQueryRequest request, boolean isNew) {
        DeviceOperLogPo queryPo = new DeviceOperLogPo();
        queryPo.setDeviceId(request.getDeviceId());
        if(isNew){
            queryPo.setFuncIds(Lists.newArrayList("2C0","410"));
        }else{
            queryPo.setFuncIds(Lists.newArrayList("210","410"));
        }
        Integer offset = (request.getPage() - 1) * request.getLimit();
        Integer limit = request.getLimit();
        List<DeviceWorkLogVo> deviceWorkLogVoList = new ArrayList<>();
        List<DeviceOperLogPo> workDataListList = this.deviceOperLogMapper.selectWorkDataList(queryPo, limit, offset);
        if (null != workDataListList && 0 < workDataListList.size()) {
            workDataListList.stream().forEach(eachPo -> {
                DeviceWorkLogVo deviceWorkLogVo = new DeviceWorkLogVo();
                if (eachPo.getFuncId().equals("410")) {
                    deviceWorkLogVo.setDeviceStatus(eachPo.getFuncValue().equals("0") ? "离线" : "上线");
                } else {
                    if (null != eachPo.getFuncValue()) {
                        deviceWorkLogVo.setDeviceStatus(eachPo.getFuncValue().equals("0") ? "关机" : "开机");
                    } else {
                        deviceWorkLogVo.setDeviceStatus("未知定时操作");
                    }
                }
                deviceWorkLogVo.setCreateTime(eachPo.getCreateTime());
                log.info("当前设备信息：{}", deviceWorkLogVo.getDeviceStatus());
                deviceWorkLogVoList.add(deviceWorkLogVo);
            });
        }
        return new ApiResponse<>(RetCode.OK, "查询工作日志成功", deviceWorkLogVoList);
    }

    public ApiResponse<List<DeviceWorkLogVo>> queryFLDeviceWorkData(DeviceDataQueryRequest request) {
        DeviceOperLogPo queryPo = new DeviceOperLogPo();
        queryPo.setDeviceId(request.getDeviceId());
        queryPo.setFuncIds(Lists.newArrayList("ON","OFF","410"));

        Integer offset = (request.getPage() - 1) * request.getLimit();
        Integer limit = request.getLimit();
        List<DeviceWorkLogVo> deviceWorkLogVoList = new ArrayList<>();
        List<DeviceOperLogPo> workDataListList = this.deviceOperLogMapper.selectWorkDataList(queryPo, limit, offset);
        if (null != workDataListList && 0 < workDataListList.size()) {
            workDataListList.stream().forEach(eachPo -> {
                DeviceWorkLogVo deviceWorkLogVo = new DeviceWorkLogVo();
                if (eachPo.getFuncId().equals("410")) {
                    deviceWorkLogVo.setDeviceStatus(eachPo.getFuncValue().equals("0") ? "离线" : "上线");
                } else {
                    if (null == eachPo.getFuncValue()) {
                        deviceWorkLogVo.setDeviceStatus("未知定时操作");
                    } else {
                        if(eachPo.getFuncId().equals("ON")){
                            deviceWorkLogVo.setDeviceStatus("开机");
                        }else{
                            deviceWorkLogVo.setDeviceStatus("关机");
                        }
                    }
                }
                deviceWorkLogVo.setCreateTime(eachPo.getCreateTime());
                log.info("当前设备信息：{}", deviceWorkLogVo.getDeviceStatus());
                deviceWorkLogVoList.add(deviceWorkLogVo);
            });
        }
        return new ApiResponse<>(RetCode.OK, "查询工作日志成功", deviceWorkLogVoList);
    }


    public ApiResponse<BaseListVo> queryDeviceWorkDataList(DeviceDataQueryRequest request) {
        DeviceOperLogPo queryPo = new DeviceOperLogPo();
        queryPo.setDeviceId(request.getDeviceId());
        ApiResponse<List<DeviceWorkLogVo>> workLogRtn;
        BaseListVo baseListVo = new BaseListVo();
        Integer workDataCount;
        //风冷热泵
        queryPo.setFuncIds(Lists.newArrayList("ON"));
        workDataCount = this.deviceOperLogMapper.selectWorkDataCount(queryPo);
        if(workDataCount > 0){
            queryPo.setFuncIds(Lists.newArrayList("ON","OFF"));
            workDataCount = this.deviceOperLogMapper.selectWorkDataCount(queryPo);
            workLogRtn = queryFLDeviceWorkData(request);
        }else{
            queryPo.setFuncIds(Lists.newArrayList("2C0"));
            workDataCount = this.deviceOperLogMapper.selectWorkDataCount(queryPo);
            if(workDataCount  > 0){
                //没有2C0
                queryPo.setFuncIds(Lists.newArrayList("2C0","410"));
                workDataCount = this.deviceOperLogMapper.selectWorkDataCount(queryPo);
                workLogRtn = queryDeviceWorkData(request, true);
            }else{
                queryPo.setFuncIds(Lists.newArrayList("210","410"));
                workDataCount = this.deviceOperLogMapper.selectWorkDataCount(queryPo);
                workLogRtn = queryDeviceWorkData(request);
            }
        }

        if (workLogRtn != null && workLogRtn.getCode() != RetCode.OK) {
            return new ApiResponse<>(RetCode.ERROR, workLogRtn.getMsg());
        }

        baseListVo.setDataList(workLogRtn.getData());
        baseListVo.setTotalCount(workDataCount);
        return new ApiResponse<>(RetCode.OK, "查询设备操作日志与总数成功", baseListVo);
    }

    public ApiResponse<List<HeadVo>> queryDeviceSensorStatHeads(DeviceDataQueryRequest deviceDataQueryRequest) {
        //获取设备的设备功能代码
        List<DeviceAbilityPo> abilityPos = this.deviceAbilityMapper.selectAbilityCodeByDeviceId(deviceDataQueryRequest.getDeviceId());
        if (CollectionUtils.isEmpty(abilityPos)) {
            return new ApiResponse<>(RetCode.OK, "该设备尚未配备传感器功能");
        }
        DevicePo devicePo = deviceMapper.selectById(deviceDataQueryRequest.getDeviceId());
        Integer modelId = devicePo.getModelId();
        DeviceModelPo deviceModelPo = deviceModelMapper.selectById(modelId);
        ModelFormatVo modelFormatVo = deviceModelService.selectModelFormatPages(modelId, deviceModelPo.getFormatId());

        abilityPos = abilityPos.stream().filter(deviceAbilityPo -> deviceAbilityPo.getAbilityType() == 1).filter(deviceAbilityPo -> {
            List<ModelFormatVo.DeviceModelFormatItemVo> deviceModelFormatItemVos = modelFormatVo.getModelFormatPages().get(0).getModelFormatItems();
            return deviceModelFormatItemVos.stream().
                    anyMatch(deviceModelFormatItemVo -> {
                        String[] abilityIds = deviceModelFormatItemVo.getAbilityId().split(",");
                        if(deviceModelFormatItemVo.getIsCheck() == null || deviceModelFormatItemVo.getIsCheck() == 1){
                            for(String abilityId : abilityIds){
                                if(org.apache.commons.lang3.StringUtils.isNotEmpty(abilityId)){
                                    if(abilityId.equals(deviceAbilityPo.getId().toString())){
                                        return true;
                                    }
                                }
                            }
                        }
                        return false;
                    });

        }).collect(Collectors.toList());


        Map<Integer, String> datas = Maps.newHashMap();
        abilityPos.forEach(deviceAbilityPo -> {
            datas.put(deviceAbilityPo.getId(), deviceAbilityPo.getAbilityCode());
        });
        List<ModelFormatVo.DeviceModelFormatItemVo> deviceModelFormatItemVos = modelFormatVo.getModelFormatPages().get(0).getModelFormatItems();
        deviceModelFormatItemVos = deviceModelFormatItemVos.stream().filter(deviceModelFormatItemVo -> {
            String[] abilitys = deviceModelFormatItemVo.getAbilityId().split(",");
            for (String abilityId : abilitys) {
                if (!StringUtils.isEmpty(abilityId) && datas.containsKey(Integer.valueOf(abilityId))) {
                    return true;
                }
            }
            return false;
        }).collect(Collectors.toList());

        List<HeadVo> headVos = Lists.newArrayList();
        for (ModelFormatVo.DeviceModelFormatItemVo deviceModelFormatItemVo : deviceModelFormatItemVos) {
            String abilityId = deviceModelFormatItemVo.getAbilityId();
            if (!StringUtils.isEmpty(abilityId)) {
                String[] codes = abilityId.split(",");

                for (String code : codes) {
                    HeadVo headVo = new HeadVo();
                    String name = deviceModelFormatItemVo.getManageShowDataName();
                    if (StringUtils.isEmpty(name)) {
                        name = deviceModelFormatItemVo.getShowName();
                    }

                    String data = datas.get(Integer.valueOf(code));
                    headVo.setDatas(data);
                    headVo.setLabel(name);
                    headVo.setLabel(deviceModelAbilityMapper.selectByModelIdAndAbilityId(modelId, abilityId).getDefinedName());
                    headVo.setUnit(SensorTypeEnums.getUnitByMark(name));
                    headVos.add(headVo);

                }
            }
        }
        return new ApiResponse<>(headVos);
    }

    public ApiResponse<List<DeviceFailureRecordVo>> queryDeviceFailureDataList(DeviceDataQueryRequest deviceDataQueryRequest) {
        List<DeviceFailureRecordVo> deviceFailureRecordVoList = new ArrayList<>();
        Integer deviceId = deviceDataQueryRequest.getDeviceId();
        List<DeviceAlarmDataPo> deviceAlarmDataPoList = deviceAlarmMapper.queryDeviceFailureDataList(deviceId);
        for (DeviceAlarmDataPo deviceAlarmDataPo : deviceAlarmDataPoList) {
            DeviceFailureRecordVo deviceFailureRecordVo = new DeviceFailureRecordVo();
            deviceFailureRecordVo.setAlarmTime(deviceAlarmDataPo.getAlarmTime());
            deviceFailureRecordVo.setContent(deviceAlarmDataPo.getContent());
            deviceFailureRecordVo.setLevel(1);
            Date recoverTime = deviceAlarmMapper.selectLastRecoverTimeByDeviceIdAndCode(deviceId, deviceAlarmDataPo.getCode(), deviceAlarmDataPo.getAlarmTime());
            deviceFailureRecordVo.setRecoverTime(recoverTime == null? null: recoverTime);
            deviceFailureRecordVo.setStatus(recoverTime == null? "故障": "正常");
            deviceFailureRecordVoList.add(deviceFailureRecordVo);
        }
        return new ApiResponse<>(deviceFailureRecordVoList);
    }


    public ApiResponse<List<DeviceAlarmVo>> queryDeviceAlarm(DeviceDataQueryRequest deviceDataQueryRequest) {
        List<DeviceAlarmVo> deviceAlarmVoList = new ArrayList<>();
        Integer deviceId = deviceDataQueryRequest.getDeviceId();
        List<DeviceAbilityPo> deviceAbilityPoList = deviceAbilityMapper.selectByModelIdAndConfigType(deviceMapper.selectById(deviceId).getModelId(), 2); //查该设备所有告警/故障功能项
        for (DeviceAbilityPo deviceAbilityPo : deviceAbilityPoList) {
            DeviceAlarmVo deviceAlarmVo = new DeviceAlarmVo();
            String code = deviceAbilityPo.getDirValue();
            deviceAlarmVo.setCode(code);
            deviceAlarmVo.setContent(deviceAbilityPo.getAbilityName());
            deviceAlarmVo.setLevel(1);
            Integer value = deviceAlarmMapper.selectStatus(deviceId, code);
            deviceAlarmVo.setStatus(value == null? "正常": value == 0? "正常" : "故障");
            deviceAlarmVoList.add(deviceAlarmVo);
        }
        return new ApiResponse<>(deviceAlarmVoList);
    }
}
